#pragma once
#include <typescommon.h>

struct list_node
{
    struct list_node *frontn; // 指向前个节点
    struct list_node *nextn;  // 指向下个节点
};
// int nodeInsertNext(struct list_node *nownode, struct list_node *innode);
// int nodeInsertFront(struct list_node *nownode, struct list_node *innode);
// int nodeDelete(struct list_node *deletenode);

struct list_node_root
{
    struct list_node *begin; // 保存第一个节点
    struct list_node *end;   // 指向下个节点
    uint32_t nodesize;
    pthread_mutex_t listlock;
};
int listRootInit(struct list_node_root *listroot);
int listRootFree(struct list_node_root *listroot);
// int listRootPushback(struct list_node_root *listroot, struct list_node *innode);
// int listRootPushfront(struct list_node_root *listroot, struct list_node *innode);
// int listRootPopback(struct list_node_root *listroot, struct list_node **outnode);
// int listRootPopfront(struct list_node_root *listroot, struct list_node **outnode);
int listRootSize(struct list_node_root *listroot);

enum listValueTypeEnum
{
    listValueTypeInt = 0,
    listValueTypeU32,
    listValueTypeS64,
    listValueTypeU64,
    listValueTypeFloat,
    listValueTypeDouble,
    listValueTypeUser,
};
// list user node struct
struct listUsrNdStct
{
    struct list_node node;
    uint32_t valtype;
    uint32_t valsize;
    union
    {
        void *valcommon;
        int32_t valint;
        uint32_t valuint;
        int64_t valint64;
        uint64_t valuint64;
        float valfloat;
        double valdouble;
        char valuser[1];
    };
};
// malloc space list user data.
struct listUsrNdStct *listUsrMlcSpc(uint32_t usertype, uint32_t userValueSize);

// list user malloc base type space
struct listUsrNdStct *listUsrMlcI32(int32_t setVal);
struct listUsrNdStct *listUsrMlcU32(uint32_t setVal);
struct listUsrNdStct *listUsrMlcI64(int64_t setVal);
struct listUsrNdStct *listUsrMlcU64(uint64_t setVal);
struct listUsrNdStct *listUsrMlcFloat(float setVal);
struct listUsrNdStct *listUsrMlcDouble(double setVal);

// list user malloc base type space, and insert to list root.
// struct listUsrNdStct *listUsrMlcIstI32(struct list_node_root *listroot, int32_t setVal);
// struct listUsrNdStct *listUsrMlcIstU32(struct list_node_root *listroot, uint32_t setVal);
// struct listUsrNdStct *listUsrMlcIstI64(struct list_node_root *listroot, int64_t setVal);
// struct listUsrNdStct *listUsrMlcIstU64(struct list_node_root *listroot, uint64_t setVal);
// struct listUsrNdStct *listUsrMlcIstFloat(struct list_node_root *listroot, float setVal);
// struct listUsrNdStct *listUsrMlcIstDouble(struct list_node_root *listroot, double setVal);

// list user push node into list root.
int listUsrPushNd(struct list_node_root *listroot, struct listUsrNdStct *unode, int optbackflag);
int listUsrPushBack(struct list_node_root *listroot, struct listUsrNdStct *unode);
int listUsrPushFront(struct list_node_root *listroot, struct listUsrNdStct *unode);

// list user pop node from list root.
struct listUsrNdStct *listUsrPopNd(struct list_node_root *listroot, int optbackflag);
struct listUsrNdStct *listUsrPopBack(struct list_node_root *listroot);
struct listUsrNdStct *listUsrPopFront(struct list_node_root *listroot);

// list user push back base type value
#define listUsrPsbkI32(lroot, setVal) (listUsrPushBack(lroot, listUsrMlcI32(setVal)))
#define listUsrPsfrI32(lroot, setVal) (listUsrPushFront(lroot, listUsrMlcI32(setVal)))
#define listUsrPsbkU32(lroot, setVal) (listUsrPushBack(lroot, listUsrMlcU32(setVal)))
#define listUsrPsfrU32(lroot, setVal) (listUsrPushFront(lroot, listUsrMlcU32(setVal)))
#define listUsrPsbkI64(lroot, setVal) (listUsrPushBack(lroot, listUsrMlcI64(setVal)))
#define listUsrPsfrI64(lroot, setVal) (listUsrPushFront(lroot, listUsrMlcI64(setVal)))
#define listUsrPsbkU64(lroot, setVal) (listUsrPushBack(lroot, listUsrMlcU64(setVal)))
#define listUsrPsfrU64(lroot, setVal) (listUsrPushFront(lroot, listUsrMlcU64(setVal)))
#define listUsrPsbkFlt(lroot, setVal) (listUsrPushBack(lroot, listUsrMlcFloat(setVal)))
#define listUsrPsfrFlt(lroot, setVal) (listUsrPushFront(lroot, listUsrMlcFloat(setVal)))
#define listUsrPsbkDbl(lroot, setVal) (listUsrPushBack(lroot, listUsrMlcDouble(setVal)))
#define listUsrPsfrDbl(lroot, setVal) (listUsrPushFront(lroot, listUsrMlcDouble(setVal)))

// struct listUsrNdStct *mallocUserNodeAndPush(struct list_node_root *listroot, uint32_t usertype, void *userdata,
//                                               uint32_t datasize, int optbackflag);
// get list user node pointer.
#define listUsrNdPtr(userNode, usrValType) ((usrValType *)(userNode->valuser))
